package com.gzsxy.esjy.service.base.handler;


import com.gzsxy.esjy.common.base.exception.impl.BusinessException;
import com.gzsxy.esjy.common.base.result.R;
import com.gzsxy.esjy.common.base.result.ResultCodeEnum;
import com.gzsxy.esjy.common.base.util.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.CredentialsException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;

/**
 * 统一异常处理器
 */

@ControllerAdvice  //做一个切面专门用来做异常处理信息
@Slf4j
public class GlobalExceptionHandler {


    private static final String STRING ="BusinessException";

    //异常处理器
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error(Exception e, HttpServletRequest request){
        String method = request.getMethod();
        String url = request.getRequestURI().toString();
        String queryString = request.getQueryString();
        StringBuffer msg = new StringBuffer();
        msg.append("请求接口发生异常:").append(method).append(" ").append(url);
        if (queryString != null){
            msg.append("?").append(queryString);
        }
//        e.printStackTrace();  //输出异常
        log.error(msg.toString(),e);  //保存在日志文件中也打印在控制台
        return R.error();
    }


    //BadSqlGrammarException异常 sql异常
    @ExceptionHandler(BadSqlGrammarException.class)
    @ResponseBody
    public R error(BadSqlGrammarException e){

//        e.printStackTrace();  //输出异常
        log.error(ExceptionUtils.getMessage(e));  //保存在日志文件中也打印在控制台
        return R.setResult(ResultCodeEnum.BAD_SQL_GRAMMAR); //sql语法错误
    }


    //HttpMessageNotReadableException// json解析异常
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public R error(HttpMessageNotReadableException e){
//        e.printStackTrace();  //输出异常
//        log.error(e.getMessage());  //保存在日志文件中也打印在控制台(只保留了错误信息)
        log.error(ExceptionUtils.getMessage(e));  //保存在日志文件中也打印在控制台（保存了所有的错误栈信息）
        return R.setResult(ResultCodeEnum.JSON_PARSE_ERROR); //json解析异常
    }


    //捕获GuliEception错误信息
    @ExceptionHandler(GuliEception.class)
    @ResponseBody
    public R error(GuliEception e){

//        e.printStackTrace();  //输出异常
//        log.error(e.getMessage());  //保存在日志文件中也打印在控制台(只保留了错误信息)
        log.error(ExceptionUtils.getMessage(e));  //保存在日志文件中也打印在控制台（保存了所有的错误栈信息）
        return R.error().message(e.getMessage()).code(e.getCode()); //封装到error
    }

    //自定义异常处理
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public R error(BusinessException e){
        log.error(ExceptionUtils.getMessage(e));
        return R.error().message(e.getMessage());
    }


    //自定义异常处理（当我们会话用户丢失抛出的异常是嵌套在MyBatisSystemException中，所以要筛出）
    @ExceptionHandler(MyBatisSystemException.class)
    @ResponseBody
    public R error(MyBatisSystemException e){
        Throwable cause = e.getCause();
        String message = cause.getMessage();
        log.error(ExceptionUtils.getMessage(e));
        //捕获BusinessException（会话用户丢失）
        if (message.contains(STRING)){
            int businessException = message.lastIndexOf(STRING);
            String substring = message.substring(businessException + STRING.length()+1);
            return R.error().message(substring);
        }
        return R.error().message(e.getMessage());
    }


    /**
     * 捕获shiro密码验证失败异常
     */
    @ExceptionHandler(CredentialsException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public R error(CredentialsException e){
        log.error("账号密码错误::{}",e.getLocalizedMessage());
        return R.error().message("账号密码错误");
    }


}
